/*!
 * \file nuRTTI.cpp
 * \brief Implementation of Run-Time Type Information.
 * \author Nus
 * \date 2008/02/02, 21:50
 */

#include "Debug.h"
#include "Utility.h"
#include "nuRTTI.h"

// Last RTTI in chain.
nuRTTI* nuRTTIMgr::mpLastRTTI = NULL;
// RTTI chain.
nuRTTI* nuRTTIMgr::mpRTTIChain = NULL;



// Constructor.
nuRTTI::nuRTTI()
    : mpNext(NULL),
      mClassHash(NULL),
      mSuperHash(NULL),
      mType(TYPE_UNINITIALIZED),
      mpChain(NULL)
{
  // None...
}
  
// Default destructor.
nuRTTI::~nuRTTI()
{
  // None...
}

// Initialize.
void nuRTTI::init(u32 type, const s8* cls, const s8* spr)
{
  if(mType == TYPE_UNINITIALIZED) {
    mClassHash = cls;
    mSuperHash = spr;
    mType = type;
    nuRTTIMgr::addRTTI(this);
  }
}
  
  


// Add RTTI.
void nuRTTIMgr::addRTTI(nuRTTI* p_class)
{
  if(mpLastRTTI) {
    mpLastRTTI->mpNext = p_class;
    mpLastRTTI = mpLastRTTI->mpNext;
  } else {
    mpRTTIChain = p_class;
    mpLastRTTI = p_class;
  }
}

// New object.
void* nuRTTIMgr::newObj(const s8* name)
{
  nuRTTI* p_rtti = mpRTTIChain;
  while(p_rtti) {
    if(Util::compareStr(p_rtti->getName(), name))
      return p_rtti->newObj();
    p_rtti = p_rtti->mpNext;
  }
  
  return NULL;
}

// New object.
void* nuRTTIMgr::newObj(const nuRTTI& my_rtti)
{
  nuRTTI* p_rtti = mpRTTIChain;
  while(p_rtti) {
    if(*p_rtti == my_rtti)
      return p_rtti->newObj();
    p_rtti = p_rtti->mpNext;
  }
  return NULL;
}

// Log RTTI.
void nuRTTIMgr::logRTTI(void)
{
  nuRTTI* p_rtti = mpRTTIChain;
  LOG("Logging RTTI...\n");
  while(p_rtti) {
    LOG("  %s - %p::%p\n", p_rtti->getName(),
        static_cast< u32 >(p_rtti->mClassHash),
        static_cast< u32 >(p_rtti->mSuperHash));
    p_rtti = p_rtti->mpNext;
  }
}
